package com.aloda.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.aloda.constant.ErrorCode;
import com.aloda.constant.ExceptionConstant;
import com.aloda.constant.UserConstant;
import com.aloda.context.UserBaseContext;
import com.aloda.dto.userToken.UserTokenAddDTO;
import com.aloda.dto.userToken.UserTokenEditDTO;
import com.aloda.entity.User;
import com.aloda.entity.UserToken;
import com.aloda.exception.BaseException;
import com.aloda.exception.WarnException;
import com.aloda.mapper.UserMapper;
import com.aloda.mapper.UserTokenMapper;
import com.aloda.query.UserTokenPageDTO;
import com.aloda.result.PageResult;
import com.aloda.service.UserTokenService;
import com.aloda.vo.userToken.UserTokenPageVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author aloda
* @description 针对表【user_token】的数据库操作Service实现
* @createDate 2025-03-31 21:11:25
*/
@Service
public class UserTokenServiceImpl extends ServiceImpl<UserTokenMapper, UserToken> implements UserTokenService {

    @Resource
    private UserTokenMapper userTokenMapper;

    @Resource
    private UserMapper userMapper;

    /**
     * 新增用户token
     *
     * @param userTokenAddDTO
     * @return
     */
    @Override
    public Long addUserToken(UserTokenAddDTO userTokenAddDTO) {
        // 1.校验参数
        if (userTokenAddDTO.getTokenNum() < 0) {
            throw new WarnException(ErrorCode.PARAMS_ERROR);
        }
        // 2.校验用户
        Long userId = userTokenAddDTO.getUserId();
        if (userId == null) {
            throw new WarnException(ErrorCode.PARAMS_ERROR);
        }
        User user = userMapper.selectById(userId);
        if (BeanUtil.isEmpty(user)) {
            throw new BaseException(ExceptionConstant.USER_NOT_EXIST);
        }
        // 3.检查token是否已存在
        LambdaQueryWrapper<UserToken> userTokenLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userTokenLambdaQueryWrapper.eq(UserToken::getUserId, userId);
        Long count = userTokenMapper.selectCount(userTokenLambdaQueryWrapper);
        if ( count > 0 ) {
            throw new BaseException(ExceptionConstant.USER_TOKEN_IS_EXIST);
        }
        // 4.新增数据
        UserToken userToken = new UserToken();
        userToken.setUserId(userId);
        userToken.setTokenNum(userTokenAddDTO.getTokenNum());
        userToken.setCreateTime(LocalDateTime.now());
        userToken.setUpdateTime(LocalDateTime.now());
        userTokenMapper.insert(userToken);
        return userToken.getId();
    }

    /**
     * 编辑用户token
     *
     * @param userTokenEditDTO
     * @return
     */
    @Override
    public Long editUserToken(UserTokenEditDTO userTokenEditDTO) {
        // 1.校验参数
        if (userTokenEditDTO.getTokenNum() < 0) {
            throw new WarnException(ErrorCode.PARAMS_ERROR);
        }
        // 2.更新数据
        UserToken userToken = new UserToken();
        userToken.setId(userTokenEditDTO.getId());
        userToken.setTokenNum(userTokenEditDTO.getTokenNum());
        userToken.setUpdateTime(LocalDateTime.now());
        userTokenMapper.updateById(userToken);
        return userToken.getId();
    }

    /**
     * 分页查询
     *
     * @param userTokenPageDTO
     * @return
     */
    @Override
    public PageResult<UserTokenPageVO> pageQuery(UserTokenPageDTO userTokenPageDTO) {
        Page<UserToken> page = userTokenPageDTO.toMpPageDefaultSortByUpdateTimeDesc();
        LambdaQueryWrapper<UserToken> userTokenLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userTokenLambdaQueryWrapper.like(userTokenPageDTO.getUserId() != null, UserToken::getUserId, userTokenPageDTO.getUserId())
                .between(userTokenPageDTO.getBeginTime() != null && userTokenPageDTO.getEndTime() != null,
                        UserToken::getCreateTime, userTokenPageDTO.getBeginTime(), userTokenPageDTO.getEndTime());
        userTokenMapper.selectPage(page, userTokenLambdaQueryWrapper);
        List<Long> idList = page.getRecords().stream().map(UserToken::getUserId).toList();
        if (idList.isEmpty()) {
            return new PageResult<>(page.getTotal(), Collections.emptyList());
        }
        Map<Long, List<User>> userMap = userMapper.selectBatchIds(idList).stream()
                .collect(Collectors.groupingBy(User::getId));
        List<UserTokenPageVO> userTokenPageVOS = page.getRecords().stream().map(userToken -> {
            UserTokenPageVO userTokenPageVO = BeanUtil.copyProperties(userToken, UserTokenPageVO.class);
            if (userMap.containsKey(userToken.getUserId())) {
                User user = userMap.get(userTokenPageVO.getUserId()).get(0);
                userTokenPageVO.setUserAccount(user.getUserAccount());
                userTokenPageVO.setNickname(user.getNickname());
            }
            return userTokenPageVO;
        }).toList();
        return new PageResult<>(page.getTotal(), userTokenPageVOS);
    }

    /**
     * 赠送新用户tokens
     *
     * @return
     */
    @Override
    public Boolean giveNewUserTokens() {
        Long userId = UserBaseContext.getUser().getId();
        LambdaQueryWrapper<UserToken> userTokenLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userTokenLambdaQueryWrapper.eq(UserToken::getUserId, userId);
        UserToken userToken = userTokenMapper.selectOne(userTokenLambdaQueryWrapper);
        if (BeanUtil.isNotEmpty(userToken)) {
            throw new WarnException(ExceptionConstant.USER_TOKEN_GIVEN);
        }
        UserToken newUserToken = new UserToken();
        newUserToken.setTokenNum((long)UserConstant.NEW_USER_TOKENS_NUM);
        newUserToken.setUserId(userId);
        newUserToken.setCreateTime(LocalDateTime.now());
        newUserToken.setUpdateTime(LocalDateTime.now());
        int insert = userTokenMapper.insert(newUserToken);
        return insert > 0;
    }
}




